package com.myself.common.service

import com.myself.common.entity.BaseEntity
import com.myself.common.page.Page
import com.myself.common.page.PageResult
import com.myself.common.repository.BaseRepository
import com.myself.common.table.BaseTable
import org.ktorm.schema.ColumnDeclaring
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.transaction.TransactionStatus
import org.springframework.transaction.annotation.Transactional
import org.springframework.transaction.support.TransactionTemplate

abstract class BaseService<T : BaseEntity<T>, B : BaseTable<T>>(
    private val repository: BaseRepository<T, B>
) {
    @Autowired
    private lateinit var transactionTemplate: TransactionTemplate

    open fun findAll(): List<T> {
        return repository.findAll()
    }

    open fun findAll(page: Page): PageResult<T> {
        return repository.findAll(page)
    }

    open fun findLast(): T? {
        return repository.findLast()
    }

    open fun findById(id: Int): T? {
        return repository.findById(id)
    }

    open fun findBy(condition: (B) -> ColumnDeclaring<Boolean>): List<T> {
        return repository.findBy(condition)
    }

    open fun findPageListBy(page: Page, condition: (B) -> ColumnDeclaring<Boolean>): PageResult<T> {
        return repository.findPageListBy(page, condition)
    }

    @Transactional
    open fun addOne(entity: T) {
        repository.addOne(entity)
    }

    @Transactional
    open fun updateOne(entity: T): Int {
        return repository.updateOne(entity)
    }

    @Transactional
    open fun updateOneBy(condition: (B) -> ColumnDeclaring<Boolean>, change: (T) -> Unit): Int {
        val also =
            repository.findOneBy(condition)?.also(change)
                ?: throw IllegalStateException("实体对象未找到")
        return repository.updateOne(also)
    }

    @Transactional
    open fun deleteOne(entity: T): Int {
        return repository.deleteOne(entity)
    }

    open fun dynamicSave(entity: T): T {
        // 1. 前置非事务检查
        saveCheck(entity)

        // 2. 使用编程式事务执行核心操作
        val savedEntity = transactionTemplate.execute { status: TransactionStatus ->
            try {
                // 3. 事务前置处理
                beforeSave(entity)

                // 4. 核心保存操作（根据权限决定创建/更新）
                val saved = saveByPermission(entity)

                // 5. 保存后
                afterSave(saved)

                saved // 返回事务结果
            } catch (e: Exception) {
                // 触发回滚（根据需要处理异常）
                status.setRollbackOnly()
                throw e
            }
        } ?: throw IllegalStateException("Transaction failed to save entity")

        afterCommit(savedEntity)

        // 7. 返回转换后的实体
        return convert(savedEntity)
    }

    // region 需要子类实现/重写的protected方法
    protected open fun saveByPermission(entity: T): T {
        return entity;
    }

    protected open fun saveCheck(entity: T) {
        // 默认空实现，子类可重写校验逻辑
        // 示例：检查字段有效性、权限校验等
    }

    protected open fun beforeSave(entity: T) {
        // 事务内预处理（如：设置审计字段）
    }

    protected open fun afterSave(entity: T) {
        // 事务外后处理（如：发送领域事件）
    }

    protected open fun beforeCommit(entity: T) {
        // 提交前最后的处理（如：更新缓存）
    }

    protected open fun afterCommit(entity: T) {
        // 提交成功后处理（如：异步通知）
    }

    protected open fun convert(entity: T): T {
        // 默认不转换，子类可重写（如：转换为DTO）
        return entity
    }
}